{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f1257c4-11f2-4f2c-b7a9-3ff7d88a844e",
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install langchain_openai langgraph langgraph-swarm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "52d21ef9-1a36-4616-bf59-6e8a0dc053cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "os.environ[\"ANTHROPIC_API_KEY\"] = \"\"\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"\"\n",
    "\n",
    "# turn on langsmith tracing\n",
    "os.environ[\"LANGSMITH_API_KEY\"] = \"\"\n",
    "os.environ[\"LANGSMITH_TRACING_V2\"] = \"true\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b00fae2b-5c83-4e23-838f-46e8fe30bffd",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "model = ChatOpenAI(model=\"gpt-4o\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bbf49378-d2b2-4e4f-a1a5-1f308c82febe",
   "metadata": {},
   "source": [
    "## Customer support tools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "6011da74-ad1e-472c-b8f3-57ecbf9fd6ba",
   "metadata": {},
   "outputs": [],
   "source": [
    "import datetime\n",
    "from collections import defaultdict\n",
    "from typing import Callable\n",
    "\n",
    "from langchain_core.runnables import RunnableConfig\n",
    "from langgraph.checkpoint.memory import MemorySaver\n",
    "from langgraph.prebuilt import create_react_agent\n",
    "from langgraph_swarm import create_handoff_tool, create_swarm\n",
    "\n",
    "# Mock data for tools\n",
    "RESERVATIONS = defaultdict(lambda: {\"flight_info\": {}, \"hotel_info\": {}})\n",
    "TOMORROW = (datetime.date.today() + datetime.timedelta(days=1)).isoformat()\n",
    "FLIGHTS = [\n",
    "    {\n",
    "        \"departure_airport\": \"BOS\",\n",
    "        \"arrival_airport\": \"JFK\",\n",
    "        \"airline\": \"Jet Blue\",\n",
    "        \"date\": TOMORROW,\n",
    "        \"id\": \"1\",\n",
    "    }\n",
    "]\n",
    "HOTELS = [\n",
    "    {\n",
    "        \"location\": \"New York\",\n",
    "        \"name\": \"McKittrick Hotel\",\n",
    "        \"neighborhood\": \"Chelsea\",\n",
    "        \"id\": \"1\",\n",
    "    }\n",
    "]\n",
    "\n",
    "\n",
    "# Flight tools\n",
    "def search_flights(\n",
    "    departure_airport: str,\n",
    "    arrival_airport: str,\n",
    "    date: str,\n",
    ") -> list[dict]:\n",
    "    \"\"\"Search flights.\n",
    "\n",
    "    Args:\n",
    "        departure_airport: 3-letter airport code for the departure airport. If unsure, use the biggest airport in the area\n",
    "        arrival_airport: 3-letter airport code for the arrival airport. If unsure, use the biggest airport in the area\n",
    "        date: YYYY-MM-DD date\n",
    "    \"\"\"\n",
    "    # return all flights for simplicity\n",
    "    return FLIGHTS\n",
    "\n",
    "\n",
    "def book_flight(\n",
    "    flight_id: str,\n",
    "    config: RunnableConfig,\n",
    ") -> str:\n",
    "    \"\"\"Book a flight.\"\"\"\n",
    "    user_id = config[\"configurable\"].get(\"user_id\")\n",
    "    flight = [flight for flight in FLIGHTS if flight[\"id\"] == flight_id][0]\n",
    "    RESERVATIONS[user_id][\"flight_info\"] = flight\n",
    "    return \"Successfully booked flight\"\n",
    "\n",
    "\n",
    "# Hotel tools\n",
    "def search_hotels(location: str) -> list[dict]:\n",
    "    \"\"\"Search hotels.\n",
    "\n",
    "    Args:\n",
    "        location: offical, legal city name (proper noun)\n",
    "    \"\"\"\n",
    "    # return all hotels for simplicity\n",
    "    return HOTELS\n",
    "\n",
    "\n",
    "def book_hotel(\n",
    "    hotel_id: str,\n",
    "    config: RunnableConfig,\n",
    ") -> str:\n",
    "    \"\"\"Book a hotel.\"\"\"\n",
    "    user_id = config[\"configurable\"].get(\"user_id\")\n",
    "    hotel = [hotel for hotel in HOTELS if hotel[\"id\"] == hotel_id][0]\n",
    "    RESERVATIONS[user_id][\"hotel_info\"] = hotel\n",
    "    return \"Successfully booked hotel\"\n",
    "\n",
    "\n",
    "# Handoff tools\n",
    "transfer_to_hotel_assistant = create_handoff_tool(\n",
    "    agent_name=\"hotel_assistant\",\n",
    "    description=\"Transfer user to the hotel-booking assistant that can search for and book hotels.\",\n",
    ")\n",
    "transfer_to_flight_assistant = create_handoff_tool(\n",
    "    agent_name=\"flight_assistant\",\n",
    "    description=\"Transfer user to the flight-booking assistant that can search for and book flights.\",\n",
    ")\n",
    "\n",
    "\n",
    "# Define agent prompt\n",
    "def make_prompt(base_system_prompt: str) -> Callable[[dict, RunnableConfig], list]:\n",
    "    def prompt(state: dict, config: RunnableConfig) -> list:\n",
    "        user_id = config[\"configurable\"].get(\"user_id\")\n",
    "        current_reservation = RESERVATIONS[user_id]\n",
    "        system_prompt = (\n",
    "            base_system_prompt\n",
    "            + f\"\\n\\nUser's active reservation: {current_reservation}\"\n",
    "            + f\"Today is: {datetime.datetime.now()}\"\n",
    "        )\n",
    "        return [{\"role\": \"system\", \"content\": system_prompt}] + state[\"messages\"]\n",
    "\n",
    "    return prompt\n",
    "\n",
    "\n",
    "# Define agents\n",
    "flight_assistant = create_react_agent(\n",
    "    model,\n",
    "    [search_flights, book_flight, transfer_to_hotel_assistant],\n",
    "    prompt=make_prompt(\"You are a flight booking assistant\"),\n",
    "    name=\"flight_assistant\",\n",
    ")\n",
    "\n",
    "hotel_assistant = create_react_agent(\n",
    "    model,\n",
    "    [search_hotels, book_hotel, transfer_to_flight_assistant],\n",
    "    prompt=make_prompt(\"You are a hotel booking assistant\"),\n",
    "    name=\"hotel_assistant\",\n",
    ")\n",
    "\n",
    "# Compile and run!\n",
    "checkpointer = MemorySaver()\n",
    "builder = create_swarm(\n",
    "    [flight_assistant, hotel_assistant], default_active_agent=\"flight_assistant\"\n",
    ")\n",
    "\n",
    "# Important: compile the swarm with a checkpointer to remember\n",
    "# previous interactions and last active agent\n",
    "app = builder.compile(checkpointer=checkpointer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "1e87a927-4f47-4ef8-a6ce-1094b31d6f24",
   "metadata": {},
   "outputs": [],
   "source": [
    "from IPython.display import Image, display"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "d48b7dd4-3bbf-46b9-b1a6-df608be11b7f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "display(Image(app.get_graph().draw_mermaid_png()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "9b54c131-b1a5-4f30-b8a4-61a950ea543a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import uuid\n",
    "\n",
    "config = {\"configurable\": {\"thread_id\": str(uuid.uuid4()), \"user_id\": \"1\"}}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "5930b465-3692-4971-b00d-cda356754f75",
   "metadata": {},
   "outputs": [],
   "source": [
    "def print_stream(stream):\n",
    "    for ns, update in stream:\n",
    "        for node, node_updates in update.items():\n",
    "            if node_updates is None:\n",
    "                continue\n",
    "\n",
    "            if isinstance(node_updates, (dict, tuple)):\n",
    "                node_updates_list = [node_updates]\n",
    "            elif isinstance(node_updates, list):\n",
    "                node_updates_list = node_updates\n",
    "            else:\n",
    "                raise ValueError(node_updates)\n",
    "\n",
    "            for node_updates in node_updates_list:\n",
    "                if isinstance(node_updates, tuple):\n",
    "                    continue\n",
    "                messages_key = next(\n",
    "                    (k for k in node_updates.keys() if \"messages\" in k), None\n",
    "                )\n",
    "                if messages_key is not None:\n",
    "                    node_updates[messages_key][-1].pretty_print()\n",
    "                else:\n",
    "                    pass\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "b61f97ff",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Namespace '('flight_assistant:84744415-e427-8fd1-f8cd-7709705ba2ba',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: flight_assistant\n",
      "Tool Calls:\n",
      "  search_flights (call_W97unU1M0IiCu0DrEmGDn5bm)\n",
      " Call ID: call_W97unU1M0IiCu0DrEmGDn5bm\n",
      "  Args:\n",
      "    departure_airport: BOS\n",
      "    arrival_airport: JFK\n",
      "    date: 2025-02-26\n",
      "\n",
      "\n",
      "\n",
      "Namespace '('flight_assistant:84744415-e427-8fd1-f8cd-7709705ba2ba',)'\n",
      "Update from node 'tools'\n",
      "=================================\u001b[1m Tool Message \u001b[0m=================================\n",
      "Name: search_flights\n",
      "\n",
      "[{\"departure_airport\": \"BOS\", \"arrival_airport\": \"JFK\", \"airline\": \"Jet Blue\", \"date\": \"2025-02-26\", \"id\": \"1\"}]\n",
      "\n",
      "\n",
      "\n",
      "Namespace '('flight_assistant:84744415-e427-8fd1-f8cd-7709705ba2ba',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: flight_assistant\n",
      "\n",
      "I found a flight for you from Boston (BOS) to New York (JFK) for tomorrow, February 26, 2025:\n",
      "\n",
      "- **Airline**: Jet Blue\n",
      "\n",
      "Would you like to book this flight?\n",
      "\n",
      "\n",
      "\n",
      "Namespace '()'\n",
      "Update from node 'flight_assistant'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: flight_assistant\n",
      "\n",
      "I found a flight for you from Boston (BOS) to New York (JFK) for tomorrow, February 26, 2025:\n",
      "\n",
      "- **Airline**: Jet Blue\n",
      "\n",
      "Would you like to book this flight?\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "===\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print_stream(\n",
    "    app.stream(\n",
    "        {\n",
    "            \"messages\": [\n",
    "                {\n",
    "                    \"role\": \"user\",\n",
    "                    \"content\": \"i am looking for a flight from boston to ny tomorrow\",\n",
    "                }\n",
    "            ]\n",
    "        },\n",
    "        config,\n",
    "        subgraphs=True,\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "0d8dc373-e4d8-4c9d-92d6-4f3dbf6a5465",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Namespace '('flight_assistant:e4a8a360-6a10-ffc1-9775-2db618706a62',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: flight_assistant\n",
      "Tool Calls:\n",
      "  book_flight (call_0yBH8MVZF8CZauwa0VrSIjDO)\n",
      " Call ID: call_0yBH8MVZF8CZauwa0VrSIjDO\n",
      "  Args:\n",
      "    flight_id: 1\n",
      "\n",
      "\n",
      "\n",
      "Namespace '('flight_assistant:e4a8a360-6a10-ffc1-9775-2db618706a62',)'\n",
      "Update from node 'tools'\n",
      "=================================\u001b[1m Tool Message \u001b[0m=================================\n",
      "Name: book_flight\n",
      "\n",
      "Successfully booked flight\n",
      "\n",
      "\n",
      "\n",
      "Namespace '('flight_assistant:e4a8a360-6a10-ffc1-9775-2db618706a62',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: flight_assistant\n",
      "\n",
      "Your flight from Boston to New York with Jet Blue on February 26, 2025, has been successfully booked. Safe travels!\n",
      "\n",
      "\n",
      "\n",
      "Namespace '()'\n",
      "Update from node 'flight_assistant'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: flight_assistant\n",
      "\n",
      "Your flight from Boston to New York with Jet Blue on February 26, 2025, has been successfully booked. Safe travels!\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "===\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print_stream(\n",
    "    app.stream(\n",
    "        {\"messages\": [{\"role\": \"user\", \"content\": \"yes please\"}]},\n",
    "        config,\n",
    "        subgraphs=True,\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b6338b25",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Namespace '('flight_assistant:470ea1ba-b5a2-6164-d6e1-b6c98519aefc',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: flight_assistant\n",
      "Tool Calls:\n",
      "  transfer_to_hotel_assistant (call_Ufumk8HdnMnO8ll294NLOyqI)\n",
      " Call ID: call_Ufumk8HdnMnO8ll294NLOyqI\n",
      "  Args:\n",
      "\n",
      "\n",
      "\n",
      "Namespace '()'\n",
      "Update from node 'flight_assistant'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: flight_assistant\n",
      "Tool Calls:\n",
      "  transfer_to_hotel_assistant (call_Ufumk8HdnMnO8ll294NLOyqI)\n",
      " Call ID: call_Ufumk8HdnMnO8ll294NLOyqI\n",
      "  Args:\n",
      "Update from node 'flight_assistant'\n",
      "=================================\u001b[1m Tool Message \u001b[0m=================================\n",
      "Name: transfer_to_hotel_assistant\n",
      "\n",
      "Successfully transferred to hotel_assistant\n",
      "Update from node 'flight_assistant'\n",
      "{'active_agent': 'hotel_assistant'}\n",
      "\n",
      "\n",
      "\n",
      "Namespace '('hotel_assistant:96312da9-559b-cfc4-43eb-73ffd7549e5a',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: hotel_assistant\n",
      "Tool Calls:\n",
      "  search_hotels (call_UbFeu8XUunTfuVLnbMgyJUPP)\n",
      " Call ID: call_UbFeu8XUunTfuVLnbMgyJUPP\n",
      "  Args:\n",
      "    location: New York\n",
      "\n",
      "\n",
      "\n",
      "Namespace '('hotel_assistant:96312da9-559b-cfc4-43eb-73ffd7549e5a',)'\n",
      "Update from node 'tools'\n",
      "=================================\u001b[1m Tool Message \u001b[0m=================================\n",
      "Name: search_hotels\n",
      "\n",
      "[{\"location\": \"New York\", \"name\": \"McKittrick Hotel\", \"neighborhood\": \"Chelsea\", \"id\": \"1\"}]\n",
      "\n",
      "\n",
      "\n",
      "Namespace '('hotel_assistant:96312da9-559b-cfc4-43eb-73ffd7549e5a',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: hotel_assistant\n",
      "\n",
      "I found a hotel for you in New York:\n",
      "\n",
      "- **Hotel Name**: McKittrick Hotel\n",
      "- **Neighborhood**: Chelsea\n",
      "\n",
      "Would you like to book a room at this hotel?\n",
      "\n",
      "\n",
      "\n",
      "Namespace '()'\n",
      "Update from node 'hotel_assistant'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: hotel_assistant\n",
      "\n",
      "I found a hotel for you in New York:\n",
      "\n",
      "- **Hotel Name**: McKittrick Hotel\n",
      "- **Neighborhood**: Chelsea\n",
      "\n",
      "Would you like to book a room at this hotel?\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "===\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print_stream(\n",
    "    app.stream(\n",
    "        {\n",
    "            \"messages\": [\n",
    "                {\"role\": \"user\", \"content\": \"now i'd like to book a hotel as well\"}\n",
    "            ]\n",
    "        },\n",
    "        config,\n",
    "        subgraphs=True,\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "7ed3b7c1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Namespace '('hotel_assistant:dafeb86b-a3cd-bd65-21b7-250fd7daf8f2',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: hotel_assistant\n",
      "Tool Calls:\n",
      "  book_hotel (call_AyZooDJt5yGaiZikmIbzoLKk)\n",
      " Call ID: call_AyZooDJt5yGaiZikmIbzoLKk\n",
      "  Args:\n",
      "    hotel_id: 1\n",
      "\n",
      "\n",
      "\n",
      "Namespace '('hotel_assistant:dafeb86b-a3cd-bd65-21b7-250fd7daf8f2',)'\n",
      "Update from node 'tools'\n",
      "=================================\u001b[1m Tool Message \u001b[0m=================================\n",
      "Name: book_hotel\n",
      "\n",
      "Successfully booked hotel\n",
      "\n",
      "\n",
      "\n",
      "Namespace '('hotel_assistant:dafeb86b-a3cd-bd65-21b7-250fd7daf8f2',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: hotel_assistant\n",
      "\n",
      "Your reservation at the McKittrick Hotel in Chelsea, New York, has been successfully booked. Enjoy your stay!\n",
      "\n",
      "\n",
      "\n",
      "Namespace '()'\n",
      "Update from node 'hotel_assistant'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: hotel_assistant\n",
      "\n",
      "Your reservation at the McKittrick Hotel in Chelsea, New York, has been successfully booked. Enjoy your stay!\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "===\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print_stream(\n",
    "    app.stream(\n",
    "        {\"messages\": [{\"role\": \"user\", \"content\": \"yes please\"}]},\n",
    "        config,\n",
    "        subgraphs=True,\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "8b890ead",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Namespace '('hotel_assistant:813f3e95-62fe-2095-d6c7-07d52a6de1ad',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: hotel_assistant\n",
      "Tool Calls:\n",
      "  transfer_to_flight_assistant (call_MpFQrEcnXvXdNBr2zCs0xgRk)\n",
      " Call ID: call_MpFQrEcnXvXdNBr2zCs0xgRk\n",
      "  Args:\n",
      "\n",
      "\n",
      "\n",
      "Namespace '()'\n",
      "Update from node 'hotel_assistant'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: hotel_assistant\n",
      "Tool Calls:\n",
      "  transfer_to_flight_assistant (call_MpFQrEcnXvXdNBr2zCs0xgRk)\n",
      " Call ID: call_MpFQrEcnXvXdNBr2zCs0xgRk\n",
      "  Args:\n",
      "Update from node 'hotel_assistant'\n",
      "=================================\u001b[1m Tool Message \u001b[0m=================================\n",
      "Name: transfer_to_flight_assistant\n",
      "\n",
      "Successfully transferred to flight_assistant\n",
      "Update from node 'hotel_assistant'\n",
      "{'active_agent': 'flight_assistant'}\n",
      "\n",
      "\n",
      "\n",
      "Namespace '('flight_assistant:56838261-9788-8e53-f605-c875e9c0336a',)'\n",
      "Update from node 'agent'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: flight_assistant\n",
      "\n",
      "Hello! I'm here to assist you with your flight needs. How can I help you today?\n",
      "\n",
      "\n",
      "\n",
      "Namespace '()'\n",
      "Update from node 'flight_assistant'\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: flight_assistant\n",
      "\n",
      "Hello! I'm here to assist you with your flight needs. How can I help you today?\n",
      "\n",
      "\n",
      "\n",
      "\n",
      "===\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print_stream(\n",
    "    app.stream(\n",
    "        {\n",
    "            \"messages\": [\n",
    "                {\"role\": \"user\", \"content\": \"i wanna talk to flight assistant now\"}\n",
    "            ]\n",
    "        },\n",
    "        config,\n",
    "        subgraphs=True,\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d6d1752",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
